import argparse
import os
from datetime import datetime

import requests
from bs4 import BeautifulSoup
import csv
import time
import logging
from pathlib import Path

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)


def get_juejin_user_info(user_id):
    """
    获取掘金指定用户的用户名和掘力值

    参数:
        user_id: 掘金用户ID

    返回:
        字典包含用户名和掘力值，失败则返回None
    """
    # 掘金用户主页URL
    url = f"https://juejin.cn/user/{user_id}"

    # 设置请求头，模拟浏览器访问
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
        "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
        "Connection": "keep-alive",
        "Upgrade-Insecure-Requests": "1",
        "Cache-Control": "max-age=0"
    }

    try:
        # 发送请求
        response = requests.get(url, headers=headers, timeout=15)
        response.raise_for_status()  # 检查请求是否成功

        # 解析HTML
        soup = BeautifulSoup(response.text, 'html.parser')

        # 获取用户名
        username_element = soup.find(class_="username")
        if not username_element:
            logger.warning(f"用户 {user_id} 未找到用户名元素")
            return None

        # 获取掘力值
        power_value = None
        # 查找包含"掘力值"的元素
        for item in soup.find_all(class_='count'):
            if '掘力值' in item.parent.text:

                power_value = item
                break

        if power_value is None:
            logger.warning(f"用户 {user_id} 未找到掘力值元素")
            power_value = 0  # 如果找不到掘力值，设置为0
        else:
            power_value = int(power_value.text.replace(",","").strip()) if power_value.text.strip() else 0  # 如果找到但值为空，也设置为0

        return {
            'user_id': user_id,
            'username': username_element.text.strip(),
            'power_value': power_value
        }

    except requests.exceptions.RequestException as e:
        logger.error(f"用户 {user_id} 请求出错: {e}")
        return None
    except Exception as e:
        logger.error(f"用户 {user_id} 解析出错: {e}")
        return None


def read_user_ids_from_csv(csv_file):
    """
    从CSV文件读取用户信息

    参数:
        csv_file: CSV文件路径

    返回:
        用户信息列表，每个元素是包含真实姓名和用户ID的字典
    """
    users = []
    try:
        with open(csv_file, 'r', encoding='utf-8') as f:
            reader = csv.reader(f)
            # 跳过表头
            next(reader)
            for row in reader:
                if len(row) >= 2:
                    users.append({
                        'real_name': row[0].strip(),
                        'user_id': row[1].strip(),
                        'date': ''
                    })
        logger.info(f"从CSV文件成功读取 {len(users)} 个用户信息")
        return users
    except FileNotFoundError:
        logger.error(f"CSV文件 {csv_file} 未找到")
        return []
    except Exception as e:
        logger.error(f"读取CSV文件出错: {e}")
        return []


def save_results_to_csv(results, output_file):
    try:
        # 检查文件是否存在，以决定是否写入表头
        file_exists = os.path.isfile(output_file)
        # 把数据追加到文件中
        with open(output_file, 'a', encoding='utf-8', newline='') as f:
            fieldnames = ['真实姓名', '用户ID', '掘金用户名', '掘力值','日期']
            writer = csv.DictWriter(f, fieldnames=fieldnames)

            # 如果文件不存在，则先写入表头
            if not file_exists:
                writer.writeheader()

            # writer.writeheader()
            for result in results:
                writer.writerow({
                    '真实姓名': result['real_name'],
                    '用户ID': result['user_id'],
                    '掘金用户名': result['username'],
                    '掘力值': result['power_value'],
                    '日期': result['date']
                })
        logger.info(f"结果已成功保存到 {output_file}")
    except Exception as e:
        logger.error(f"保存结果到CSV文件出错: {e}")


def update_date_field(users, csv_output_file):
    try:
        # 读取CSV文件中的数据
        with open(csv_output_file, 'r', encoding='utf-8') as f:
            reader = csv.reader(f)
            # 跳过表头
            next(reader)
            for row in reader:
                if len(row) >= 2:
                    # 找到对应的用户
                    for user in users:
                        if user['user_id'] == row[1]:
                            # 更新日期字段
                            user['date'] = row[4]
                            break
    except FileNotFoundError:
        logger.error(f"CSV文件 {csv_output_file} 未找到")
    except Exception as e:
        logger.error(f"读取CSV文件出错: {e}")

def main(csv_input_file, csv_output_file, delay_seconds=2):
    """主函数"""

    # 读取用户信息
    users = read_user_ids_from_csv(csv_input_file)
    if not users:
        logger.error("没有可处理的用户信息，程序退出")
        return

    # 补充一个函数
    # 传入 users 和 csv_output_file
    # 根据csv_output_file中的信息，更新每个用户数据的最新更新日期
    # 更新users中的日期字段


    # 调用函数
    update_date_field(users, csv_output_file)


    # 处理每个用户
    results = []
    total = len(users)

    for i, user in enumerate(users, 1):
        logger.info(f"正在处理用户 {i}/{total}")


        # 如果这个用户是今天已经更新过的，就跳过
        if user['date'] == datetime.now().strftime('%Y-%m-%d'):
            #logger.info(f"用户 {user['real_name']} 今天已经更新过了，跳过")
            continue

        # 获取用户信息
        user_info = get_juejin_user_info(user['user_id'])

        if user_info:

            result = {
                'real_name': user['real_name'],
                'user_id': user['user_id'],
                'username': user_info['username'],
                'power_value': user_info['power_value'],
                # 填入当前的日期
                'date': datetime.now().strftime('%Y-%m-%d')
                
            }
            results.append(result)
            # logger.info(f"成功获取信息 - 用户名: {user_info['username']}, 掘力值: {user_info['power_value']}")
        else:
            logger.error(f"无法获取用户 {user['real_name']} 的信息")

        # 控制请求频率，避免被反爬
        if i < total:
            time.sleep(delay_seconds)

    # 保存结果
    if results:
        save_results_to_csv(results, csv_output_file)

    logger.info("程序执行完毕")


if __name__ == "__main__":
    # 输入CSV文件路径（包含真实姓名和用户ID）
    # INPUT_CSV = "users/4.csv"
    # # 输出CSV文件路径（保存结果）
    # OUTPUT_CSV = "results/result_4.csv"
    # # 每个请求之间的延迟时间（秒），可根据需要调整
    # REQUEST_DELAY = 2
    #
    # main(INPUT_CSV, OUTPUT_CSV, REQUEST_DELAY)
    # # 启动 Flask 应用
    # from app import app
    # app.run(debug=True)
    logger.info("程序开始执行")
    parser = argparse.ArgumentParser(description="抓取并保存掘金用户掘力值信息。")
    parser.add_argument(
        "--classes",
        type=str,
        nargs='+',  # 允许接收一个或多个值
        #required=True,  # 设为必需参数
        help="要处理的班级名称列表，例如：class1 class2。如果提供 'all'，则处理 users 目录下所有班级。",
        default='all' ## all
    )
    parser.add_argument(
        "--delay",
        type=int,
        default=2,
        help="每次请求之间的延迟秒数。"
    )

    parser.add_argument(
        "--show",
        type=str,
        default='1',
        help="显示哪个班的数据"
    )

    args = parser.parse_args()

    # 定义基础目录
    input_dir = "users"
    output_dir = "results"

    # 确保输出目录存在
    os.makedirs(output_dir, exist_ok=True)

    # 获取所有待处理的班级
    if 'all' in args.classes:
        # 如果参数包含 'all'，则获取 users 目录下所有 .csv 文件（不含扩展名）
        class_names = [os.path.splitext(f)[0] for f in os.listdir(input_dir) if f.endswith('.csv')]
    else:
        # 否则，使用提供的班级名称列表
        class_names = args.classes

    # 遍历每个班级，进行处理
    for class_name in class_names:
        input_csv = os.path.join(input_dir, f"{class_name}.csv")
        output_csv = os.path.join(output_dir, f"result_{class_name}.csv")

        logger.info(f"--- 开始处理班级: {class_name} ---")
        main(input_csv, output_csv, args.delay)
        logger.info(f"--- 班级 {class_name} 处理完毕 ---")

    # 启动 Flask 应用
    # 注意：这里需要决定如何处理多个数据源。一个简单的方案是只启动最后一个班级的看板。
    # 更好的方案是修改 Flask 应用，让它能动态切换数据源，但这需要更多改动。
    # 这里我们先保持简单，只启动最后一个。
    # if class_names:
    #     last_class = class_names[-1]
    #     last_output_csv = os.path.join(output_dir, f"juejin_user_info_results_{last_class}.csv")
    #     logger.info(f"启动 Flask 应用，数据源: {last_output_csv}")
    from app import start_app

    start_app(csv_file=args.show)

